package org.jackysoft.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.joda.time.DateTime;
import java.util.Collection;
import java.util.Iterator;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.jackysoft.entity.ArmItem;
import org.jackysoft.entity.ArmMonthlySemiManufacturedProductReporter;
import org.jackysoft.entity.DataItem;
import org.jackysoft.entity.Department;
import org.jackysoft.entity.ForwardStore;
import org.jackysoft.entity.OfficeDocument;
import org.jackysoft.entity.ProductType;
import org.jackysoft.entity.User;
import org.jackysoft.report.DataItemType;
import org.jackysoft.report.ReportConstant;
import org.jackysoft.report.ReporterLifecycle;
import org.jackysoft.report.rows.ArmItemSemiRowWatcher;
import org.jackysoft.report.visitor.ArmMonthlySemiManufacturedAccumulativeVisitor;
import org.jackysoft.service.AbstractReportServiceImpl;
import org.jackysoft.service.ArmMonthlySemiManufacturedReporterService;
import org.jackysoft.service.ForwardStoreService;
import org.jackysoft.util.AttachmentType;
import org.jackysoft.util.IOUtils;
import org.jackysoft.util.RowWatcher;
import org.jackysoft.util.SOAOfficeUtil;
import org.jackysoft.util.SpringSecurityUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;

/**
 * 半成品报表业务实现
 * */

@Service(ReportConstant.SemiManufacturedProductReporter)
@Transactional
public class ArmMonthlySemiManufacturedReporterServiceImpl 
extends	AbstractReportServiceImpl<ArmMonthlySemiManufacturedProductReporter>
implements ArmMonthlySemiManufacturedReporterService{

	/**
	 * 
	 */
	private static final long serialVersionUID = 637934471881540397L;
  
	private static final Log logger = LogFactory.getLog(ArmMonthlySemiManufacturedReporterServiceImpl.class);
	private ForwardStoreService forwardService;
    public ArmMonthlySemiManufacturedReporterServiceImpl() {
		this.type = ArmMonthlySemiManufacturedProductReporter.class;
	}

	@Override
	public void update(ArmMonthlySemiManufacturedProductReporter t)
			throws DataAccessException {
		
		ArmMonthlySemiManufacturedProductReporter at = get(t.getId());
		ArmMonthlySemiManufacturedProductReporter  last =  at.getLast();
		at.setCreateDate(t.getCreateDate());
		at.setDepartment(t.getDepartment());		
		at.setMaker(t.getMaker());	
		at.setLast(last);
		at.getArmItems().clear();
		at.getArmItems().addAll(t.getArmItems());
		updateAccumulate(at,last);
		super.update(at);
	}

	@Override
	public void create(ArmMonthlySemiManufacturedProductReporter t)
			throws DataAccessException {
		User user = SpringSecurityUtils.getCurrentUser();
		t.setMaker(user);
		Department dept = user.getDepartment();
		t.setDepartment(dept);
		
		ArmMonthlySemiManufacturedProductReporter  last = get(getLast(dept));
		
		//统计期初
		statForward(t);
		//更新累计
		updateAccumulate(t,last);
		//统计期末
		statFinalStore(t);
		t.setLast(last);
		t.setReportLifecycle(ReporterLifecycle.MonthSemi);
		super.create(t);
	}
	
	
	/**
	 * 统计期初结存,包括年初和月初次数据项,需要现有数据项新增加
	 * 
	 * @param T 数据项
	 **/
	protected void statForward(ArmMonthlySemiManufacturedProductReporter t) {
		// 去年最后一个月
		DateTime cal = t.getCreateDate();
		int year = cal.getYear();
		// 今年最后一张报表
		ArmMonthlySemiManufacturedProductReporter thisYear = lastOfYear(year,t.getDepartment());
		DateTime prevYear = cal.minusYears(1);
	    year = prevYear.getYear();
		// 去年最后一张报表
		ArmMonthlySemiManufacturedProductReporter lasterYear = lastOfYear(year,t.getDepartment());
		
		//上月
		DateTime lastMonth = t.getCreateDate();
		DateTime prevMonth = lastMonth.minusMonths(1);
		int month = prevMonth.getMonthOfYear();
		year  = lastMonth.getYear();
		for (ArmItem ai : t.getArmItems()) {
            if(ai==null)continue;
			DataItem di = dataItemUtil.getDataItem(ai,DataItemType.ForwardStore);
			if(di==null){
				di = new DataItem();
				ai.getDataItems().put(DataItemType.ForwardStore.toString(), di);
			}
			ForwardStore forward = forwardService.get(t.getDepartment(),year,month, ai.getHost(),ai.getItemType());
						
			// 统计月初
			if (thisYear != null) {
				
				ArmItem target = reportUtil.findByCode(thisYear.getArmItems(), ai);
				if (target != null) {
					
					di.setAccumulateValue(dataItemUtil.getDataItemAtom(target,DataItemType.FinalStore));
				}else if(forward!=null){
					
					di.setAccumulateValue(forward.getMonthValue());
				}
			}
			// 统计年初
			if (lasterYear != null) {
				ArmItem target = reportUtil.findByCode(lasterYear.getArmItems(), ai);
				if (target != null) {
					
					di.setAtomValue(dataItemUtil.getDataItemAtom(target,DataItemType.FinalStore));
				}else if(forward!=null){
					
					di.setAtomValue(forward.getYearValue());
				}
			}
		}
	}

	@Resource(name=ReportConstant.MonthlySemiManufacturedProductVisitor)
	public void setAccumulateVisitor(ArmMonthlySemiManufacturedAccumulativeVisitor accumulateVisitor) {
		super.setAccumulateVisitor(accumulateVisitor);
	}


	/**
	 * 统计月末在产
	 * */
	private void statFinalStore(ArmMonthlySemiManufacturedProductReporter t) {
		for (ArmItem arm : t.getArmItems()) {
			if (arm == null)continue;
			
			// 期初结存-月初
			Double forward = dataItemUtil.getDataItemAtom(arm,DataItemType.ForwardStore);
			// 本期收入-当月
			Double localIn = dataItemUtil.getDataItemAccumulation(arm,DataItemType.LocalIn);
			// 合格-当月
			Double localOut =dataItemUtil. getDataItemAccumulation(arm,DataItemType.LocalOut);
			// 废品-当月
			Double waster = dataItemUtil.getDataItemAccumulation(arm,DataItemType.Waster);
			// 试销-当月
			Double increment = dataItemUtil.getDataItemAccumulation(arm,DataItemType.Increment);
			// 期末结存数
			Double finalStore = forward + localIn - localOut - waster + increment;
			DataItem finalData = dataItemUtil.getDataItem(arm,DataItemType.FinalStore);
			if (finalData == null){
				finalData = new DataItem();
				arm.getDataItems().put(DataItemType.FinalStore.toString(), finalData);
			}
			finalData.setAtomValue(finalStore);
			
		}

	}

	@Override
	public Double restProductOfYear(String code,int year) throws DataAccessException {
         throw new java.lang.UnsupportedOperationException("方法未实现");		
	}

	@Override
	public Double currentRestProduct(String code) throws DataAccessException {
		 throw new java.lang.UnsupportedOperationException("方法未实现");		
	}
	
	@Override
	public ArmMonthlySemiManufacturedProductReporter getLastOfYesteryear(
			int year) throws DataAccessException {		
		return null;
	}

	byte[] getNewDraft() {
		InputStream ins = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			org.springframework.core.io.Resource res = resourceLoader
					.getResource("classpath:product-semi.xls");
			ins = res.getInputStream();
			IOUtils.copy(ins, bos);
		} catch (IOException e) {
			logger.error(e);
			e.printStackTrace();
		} finally {
			try {
				ins.close();
			} catch (IOException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return bos.toByteArray();
	}
	
	@Override
	public byte[] getResearchBytes(String id, boolean regenate) {
		if (regenate)
			return getNewDraft();

		ArmMonthlySemiManufacturedProductReporter me = get(id);
		byte[] bs = getNewDraft();

		if (me != null) {
			if (me.getResearch() != null) {
				bs = me.getResearch().getData();
				return bs;
			} else {
				return getNewDraft();
			}

		}
		
	

		return bs;
	}

	@Override
	public void updateResearch(String id) {
		ArmMonthlySemiManufacturedProductReporter ar = get(id);
		if (ar == null) {
			logger.warn(" id with  '" + id
					+ "' not found for ArmMonthlySemiManufacturedProductReporter ");
			return;

		}

		byte[] content = SOAOfficeUtil.parseSOAOfficeStream();

		if (ar.getResearch() == null) {
			OfficeDocument od = new OfficeDocument();
			od.setExt("xls");
			od.setType(AttachmentType.EXCEL);
			ar.setResearch(od);
		}

		OfficeDocument ott = ar.getResearch();
		ott.setData(content);
		Collection<ArmItem> ais = Lists.newArrayList();
		checkForNewProduct(content, ar.getDepartment(), new ArmItemSemiRowWatcher(ais, productService, ar.getDepartment(), dataItemUtil, true,ProductType.科研产品));
		ar.getArmItems().addAll(ais);
		
	}
	
    
	private void checkForNewProduct(byte[] content, Department department,RowWatcher rw) {
		if (content == null || content.length == 0)
			return;
		ByteArrayInputStream bis = new ByteArrayInputStream(content);
		try {
			HSSFWorkbook wb = new HSSFWorkbook(bis);
			int sheetCount = wb.getNumberOfSheets();
			for (int s = 0; s < sheetCount; s++) {
				Sheet sheet = wb.getSheetAt(s);
				Iterator<Row> rowItr = sheet.rowIterator();
				boolean first = true;
				while (rowItr.hasNext()) {
					Row row = rowItr.next();
					if (first) {
						first = false;
						continue;
					}
					rw.accept(row);
				}
			}

		} catch (IOException e) {
			logger.error(e);
			e.printStackTrace();
		}
		
	}

	@Resource
	public void setForwardService(ForwardStoreService forwardService) {
		this.forwardService = forwardService;
	}
	
}
